package com.supplychainapi.filter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.supplychainapi.common.RestResponse;
import com.supplychainapi.domain.JwtSubjectEntity;
import com.supplychainapi.domain.LoginCache;
import com.supplychainapi.filter.annotation.Auth;
import com.supplychainapi.model.Tbuser;
import com.supplychainapi.service.RedisService;
import com.supplychainapi.service.TbuserService;
import com.supplychainapi.utils.Constants;
import com.supplychainapi.utils.JwtUtil;
import com.supplychainapi.utils.MD5Utils;
import io.jsonwebtoken.Claims;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * 手机端签名验证
 *
 * @author xiezhiwei
 */
@Component
public class PhoneAuthIntercepter implements HandlerInterceptor {

    private Logger logger = LoggerFactory.getLogger(PhoneAuthIntercepter.class);

    @Autowired
    private JwtUtil jwtUtil;

    @Autowired
    private RedisService redisService;

    @Autowired
    private TbuserService tbuserService;

    // 公共参数
    private Map<String, String> commonParameters = new HashMap<String, String>();

    // 通过token解析出来的店铺id和用户id
    private JwtSubjectEntity jwtSubjectEntity = new JwtSubjectEntity();

    // 用户唯一标识
    private String token = "";


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }

        logger.info("权限验证");

        token = request.getHeader("Token");
        // 判断token是否合法
        if (StringUtils.isBlank(token)) {
            responseResult(response, RestResponse.fail(400, 400001, "参数错误"));
            return false;
        }

        try {
            Claims claims = jwtUtil.parseJWT(token);
            jwtSubjectEntity = JwtUtil.parseSubject(claims.getSubject());
        } catch (Exception e) {
            responseResult(response, RestResponse.fail(400, 400001, "参数错误"));
            return false;
        }

        String redisTokenKey = Constants.SCM_PHONE_PREFIX + MD5Utils.MD5Encode(token);

        String loginCacheJSON = redisService.get(redisTokenKey);
        // jwtToken 空, 获取jwtToken中存储的店铺唯一ID和用户id, 重新做登录缓存
        if (StringUtils.isBlank(loginCacheJSON)) {
            String fsShopGUID = jwtSubjectEntity.getFsShopGUID();
            String fsUserId = jwtSubjectEntity.getFsUserId();
            if (StringUtils.isBlank(fsUserId) || StringUtils.isBlank(fsShopGUID)) {
                responseResult(response, RestResponse.fail(400, "请先登录"));
                return false;
            }
            Tbuser filter = new Tbuser();
            filter.setFsShopGUID(fsShopGUID);
            filter.setFsUserId(fsUserId);
            Tbuser user = tbuserService.findOne(filter);
            // 缓存用户数据
            tbuserService.LoginCache(fsShopGUID, redisTokenKey, user);
            loginCacheJSON = redisService.get(redisTokenKey);
        }

        // 解析登录缓存
        LoginCache cache = JSONObject.parseObject(loginCacheJSON, LoginCache.class);
        // 将登录缓存的数据设置到request中
        request.setAttribute("userInfo", cache);

        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        // 判断接口是否需要登录
        Auth methodAnnotation = method.getAnnotation(Auth.class);

        // 有 @LoginRequired 注解，需要认证
        if (methodAnnotation != null) {
            String auth = methodAnnotation.auth();
            if (!StringUtils.isBlank(auth)) {
                HashMap<String, HashMap<String, String>> userAuth = cache.getAuth();
                String[] prog = auth.split("_");
                // 验证权限是否存在
                if (!(userAuth.containsKey(prog[0]) && userAuth.get(prog[0]).containsKey(prog[1]))) {
                    responseResult(response, RestResponse.fail(400, "接口无权限"));
                    return false;
                }
            }
        }

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
        logger.info("-----postHandle-----");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        logger.info("-----afterCompletion-----");
    }

    /**
     * 后台的请求进行统一日志处理
     *
     * @param request
     */
    private void loggerInfo(HttpServletRequest request) {
        String url = request.getRequestURL().toString();
        String method = request.getMethod();
        String uri = request.getRequestURI();
        String queryString = request.getQueryString();
//		System.out.println(request.getParameterMap());
        logger.info(String.format("请求参数, url: %s, method: %s, uri: %s, params: %s", url, method, uri, queryString));
    }


    /**
     * 回写json数据
     *
     * @param response
     * @param result
     */
    private void responseResult(HttpServletResponse response, RestResponse result) {
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-type", "application/json;charset=UTF-8");
        response.setStatus(200);
        try {
            response.getWriter().write(JSON.toJSONString(result));
        } catch (IOException ex) {
            logger.error(ex.getMessage());
        }
    }
}
